import wx

from .xrc.shellWait_xrc import xrcShellWait

class RemoteWait(xrcShellWait):

    sshProc = None
    _app = None
    _inputMatcher = None
    _savedStdout = _savedStderr = ""
    MAX_BAR_VALUE = 100
    BAR_STEP = 10

    def __init__(self, parent, app):
        super(RemoteWait, self).__init__(parent)
        self._app = app

    def attachToSshProcess(self, sshProc,
        showStdout=False, showStderr=False, allowInput=False,
        requestInputMatch=None):
        """Attach to given `sshProc`.

        Parameters:
            showStdout -- display process stdout in embedded text control.
            showStderr -- display process stderr in embedded text control.
            allowInput -- allow user to interact with attached process.
            requestInputMatch -- when given callabe returns 'True'
                this window will extend it's panel and ask user for input.
                (as argument to callabe all received data is given).

        """
        _showStreams = bool(showStdout or showStderr)
        _userWait = callable(requestInputMatch)
        self._inputMatcher = requestInputMatch
        if not _showStreams and _userWait:
            raise Exception(
                "You must provide at least one stream to match to")
        if showStdout:
            # a bit ugly here: if given value is string, than assume
            # that this string is an encoding name
            if isinstance(showStdout, basestring):
                _enc = showStdout
            else:
                _enc = "ascii"
            sshProc.addStdoutHandler(lambda data: self.addOutput(data, _enc))
            if _userWait:
                sshProc.addStdoutHandler(self.tryMatchStdout)
        if showStderr:
            # a bit ugly here: if given value is string, than assume
            # that this string is an encoding name
            if isinstance(showStderr, basestring):
                _enc = showStderr
            else:
                _enc = "ascii"
            sshProc.addStderrHandler(lambda data: self.addOutput(data, _enc))
            if _userWait:
                sshProc.addStdoutHandler(self.tryMatchStderr)
        self.cmdInput.Enable(allowInput)
        self.commandOutput.Clear()
        self.progressBar.SetValue(0)
        self.executedCommand.SetValue(sshProc.getCommand())
        self.sshProc = sshProc
        sshProc.addPollCallback(self._onSshPoll)
        sshProc.addDeathCallback(self.Destroy)

    def tryMatchStdout(self, data):
        self._savedStdout += data
        if self._inputMatcher(self._savedStdout):
            self._savedStdout = ""
            self.promptUser()

    def tryMatchStderr(self, data):
        self._savedStderr += data
        if self._inputMatcher(self._savedStderr):
            self._savedStderr = ""
            self.promptUser()

    def promptUser(self):
        self.streamPanel.Collapse(False)
        self.cmdInput.Enable(True)
        self.cmdInput.SetFocus()

    def addOutput(self, text, encoding="ascii"):
        self.commandOutput.AppendText(text.decode(encoding))

    def _onSshPoll(self):
        _pos = self.progressBar.GetValue() + self.BAR_STEP
        _pos = _pos % self.MAX_BAR_VALUE
        self.progressBar.SetValue(_pos)
        self._app.wxApp.Yield()

    def OnText_enter_cmdInput(self, evt):
        _cmd = self.cmdInput.GetValue()
        self.cmdInput.SetValue("")
        self.sshProc.stdin.write(_cmd + "\n")
        self.sshProc.stdin.flush()

# vim: set sts=4 sw=4 et :
